/* @flow */

import {  mergeOptions } from '../util/options'
import { extend } from '../../util/index'
import { ASSET_TYPES } from '../../util/constants'

export function initExtend(Vue) {
  Vue.cid = 0
  let cid = 1

  Vue.extend = function (extendOptions) {
    extendOptions = extendOptions || {}
    const Super = this
    const SuperId = Super.cid

    const Sub = function VueComponent(options) {
      this._init(options)
    }
    /**
     * 继承构造器，这里Super = Vue.prototype , 属性如下：
     * $delete, $destroy, $emit, $forceUpdate, $mount, $nextTick, $off, $on, $once, $set, $watch
     * _b, _d, _e, _f, _g, _i, _k, _l, _m,_n, _o, _p, _q, _s, _t, _u, _v
     * _update, __patch__, _init: ƒ (options), _render: ƒ ()
     * $data: undefined
     * $isServer: false
     * $props: undefined
     * $ssrContext: undefined
     */
    Sub.prototype = Object.create(Super.prototype)
    // 重新指向构造器
    Sub.prototype.constructor = Sub
    Sub.cid = cid++

    //合并配置项
    Sub.options = mergeOptions(
      Super.options, // Vue 全局配置components, filters, directives
      extendOptions, //组件自己的配置项
    )

    Sub['super'] = Super //指向根Vue

    // allow further extension/mixin/plugin usage
    Sub.extend = Super.extend
    Sub.mixin = Super.mixin
    Sub.use = Super.use

    //component ,  filter , directive
    ASSET_TYPES.forEach(function (type) {
      Sub[type] = Super[type]
    })

    // 在扩展时保留对超级选项的引用
    // 稍后在实例化时，我们可以检查Super的选项是否有更新
    Sub.superOptions = Super.options //{components， directives, filters, _base}
    Sub.extendOptions = extendOptions //component传递的配置项
    Sub.sealedOptions = extend({}, Sub.options) //component传递的配置和Vue合并后的配置项
    return Sub
  }
}

